package com.lhz.common.utils.http;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import javax.net.ssl.X509TrustManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;

/**
 * 通用http发送方法
 *
 * @author ruoyi
 */
@Slf4j
public class HttpUtils {
    public static void main(String[] args) {
        String url = "http://127.0.0.1:9092/system/user";
        // 设置参数
        Map<String, Object> params = new HashMap<>();
        params.put("name", "测试");
        params.put("deptId", 123);
        // 设置header
        Map<String, String> headers = new HashMap<>();
        headers.put("token", "123456789");
        String get = sendGet(url, params, headers);
        System.out.println(get);

        String s = sendDelete("http://localhost:9999/wechat/code/123456789", headers);
        System.out.println(s);
    }

    /**
     * 将Map转换为字符串参数
     *
     * @param map
     * @return
     */
    public static String mapToParamStr(Map<String, Object> map) {
        StringBuilder params = new StringBuilder();
        try {
            int size = map.size();
            int index = 1;
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                Object valueObj = entry.getValue();
                if (valueObj instanceof String) {
                    valueObj = URLEncoder.encode(valueObj.toString(), StandardCharsets.UTF_8);
                }
                params.append(entry.getKey()).append("=").append(valueObj);
                if (index != size) {
                    params.append("&");
                }
                index++;
            }
        } catch (Exception e) {
            throw new RuntimeException("参数转换失败!");
        }
        return params.toString();
    }

    /**
     * 向指定 URL 发送GET方法的请求
     *
     * @param url    发送请求的 URL
     * @param params 请求参数
     * @return 所代表远程资源的响应结果
     */
    public static String sendGet(String url, Map<String, Object> params) {
        return sendGet(url, params, "UTF-8", null);
    }

    /**
     * 向指定 URL 发送GET方法的请求
     *
     * @param url     发送请求的 URL
     * @param params  请求参数
     * @param headers 自定义请求头
     * @return 所代表远程资源的响应结果
     */
    public static String sendGet(String url, Map<String, Object> params, Map<String, String> headers) {
        return sendGet(url, params, "UTF-8", headers);
    }

    /**
     * 向指定 URL 发送GET方法的请求
     *
     * @param url         发送请求的 URL
     * @param params      请求参数
     * @param contentType 编码类型
     * @return 所代表远程资源的响应结果
     */
    public static String sendGet(String url, Map<String, Object> params, String contentType, Map<String, String> headers) {
        StringBuilder result = new StringBuilder();
        BufferedReader in = null;
        String param = mapToParamStr(params);
        try {
            String urlNameString = url + "?" + param;
            log.info("sendGet - {}", urlNameString);
            URL realUrl = new URL(urlNameString);
            URLConnection connection = realUrl.openConnection();
            // 设置头
            if (headers != null) {
                for (Map.Entry<String, String> header : headers.entrySet()) {
                    connection.setRequestProperty(header.getKey(), header.getValue());
                }
            }
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            connection.connect();
            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
            log.info("recv - {}", result);
        } catch (ConnectException e) {
            log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
        } catch (SocketTimeoutException e) {
            log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
        } catch (IOException e) {
            log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
        } catch (Exception e) {
            log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception ex) {
                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
            }
        }
        return result.toString();
    }

    /**
     * 向指定 URL 发送Post或者Put方法的请求
     *
     * @param url    发送请求的 URL
     * @param params 请求参数
     * @return 所代表远程资源的响应结果
     */
    public static String sendPostOrPut(String url, HttpMethod httpMethod, Map<String, Object> params) {
        return sendPostOrPut(url, httpMethod, params, "UTF-8", null);
    }

    /**
     * 向指定 URL 发送Post或者Put方法的请求
     *
     * @param url     发送请求的 URL
     * @param params  请求参数
     * @param headers 自定义请求头
     * @return 所代表远程资源的响应结果
     */
    public static String sendPostOrPut(String url, HttpMethod httpMethod, Map<String, Object> params, Map<String, String> headers) {
        return sendPostOrPut(url, httpMethod, params, "UTF-8", headers);
    }

    /**
     * 向指定 URL 发送Post或者Put方法的请求
     *
     * @param url         发送请求的 URL
     * @param params      请求参数
     * @param contentType 编码类型
     * @param headers     自定义请求头
     * @return 所代表远程资源的响应结果
     */
    public static String sendPostOrPut(String url, HttpMethod httpMethod, Map<String, Object> params, String contentType, Map<String, String> headers) {
        BufferedReader in = null;
        StringBuilder result = new StringBuilder();
        String param = mapToParamStr(params);
        try {
            String urlNameString = url + "?" + param;
            log.info("sendPostOrPut - {}", urlNameString);
            URL realUrl = new URL(urlNameString);
            HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
            // 设置头
            if (headers != null) {
                for (Map.Entry<String, String> header : headers.entrySet()) {
                    conn.setRequestProperty(header.getKey(), header.getValue());
                }
            }
            // 设置请求方法
            conn.setRequestMethod(httpMethod.toString());
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("contentType", "application/json;charset=UTF-8");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), contentType));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
            log.info("recv - {}", result);
        } catch (ConnectException e) {
            log.error("调用HttpUtils.sendPostOrPut ConnectException, url=" + url + ",param=" + param, e);
        } catch (SocketTimeoutException e) {
            log.error("调用HttpUtils.sendPostOrPut SocketTimeoutException, url=" + url + ",param=" + param, e);
        } catch (IOException e) {
            log.error("调用HttpUtils.sendPostOrPut IOException, url=" + url + ",param=" + param, e);
        } catch (Exception e) {
            log.error("调用HttpsUtil.sendPostOrPut Exception, url=" + url + ",param=" + param, e);
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
            }
        }
        return result.toString();
    }

    /**
     * DELETE请求
     *
     * @param url
     * @param headers 请求头
     * @return
     */
    public static String sendDelete(String url, Map<String, String> headers) {
        BufferedReader in = null;
        StringBuilder result = new StringBuilder();
        try {
            log.info("sendDelete - {}", url);
            URL realUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
            // 设置头
            if (headers != null) {
                for (Map.Entry<String, String> header : headers.entrySet()) {
                    conn.setRequestProperty(header.getKey(), header.getValue());
                }
            }
            // 设置请求方法
            conn.setRequestMethod("DELETE");
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("contentType", "application/x-www-form-urlencoded");
            conn.setDoInput(true);
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
            log.info("recv - {}", result);
        } catch (ConnectException e) {
            log.error("调用HttpUtils.sendDelete ConnectException, url=" + url, e);
        } catch (SocketTimeoutException e) {
            log.error("调用HttpUtils.sendDelete SocketTimeoutException, url=" + url, e);
        } catch (IOException e) {
            log.error("调用HttpUtils.sendDelete IOException, url=" + url, e);
        } catch (Exception e) {
            log.error("调用HttpsUtil.sendDelete Exception, url=" + url, e);
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                log.error("调用in.close Exception, url=" + url, ex);
            }
        }
        return result.toString();
    }

    private static class TrustAnyTrustManager implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[]{};
        }
    }

    private static class TrustAnyHostnameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }
}